package com.fpost.action;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.fpost.constants.ActionConstants;
import com.fpost.constants.CommonConstants;
import com.fpost.domain.ArticleRating;
import com.fpost.form.ArticlePresentationForm;
import com.fpost.form.dto.UserDTO;
import com.fpost.manager.ArticleManager;
import com.fpost.manager.ArticleRatingManager;
import com.fpost.security.ActionSecurityUtils;
import com.fpost.util.CommonUtils;
import com.fpost.util.DateUtil;

public class ArticleRatingAction extends Action {
	
	private static Logger log = Logger.getLogger(ArticleRatingAction.class);
	
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		//set current path in session
		CommonUtils.setCurrentPathInSession(request, mapping);
		
		String forward = ActionConstants.SUCCESS;
		ArticlePresentationForm presentationForm = (ArticlePresentationForm) form;

		try {
			//String ratingStr = (String) request.getParameter("rating");
			String ratingStr = presentationForm.getRating();
			String articleIdStr = (String) request.getParameter("articleId");
			
			if (articleIdStr != null && ratingStr != null) {
				long articleId = Long.parseLong(articleIdStr);
				int rating = Integer.parseInt(ratingStr);
				
				ArticleRating articleRating = new ArticleRating();
				articleRating.setArticle(new ArticleManager().getArticleById(articleId));
				articleRating.setRating(rating);
				articleRating.setCreatedOn(DateUtil.getGMTCalendar().getTime());				
				
				UserDTO userDTO = ActionSecurityUtils.getUserDTO_fromSession(request);
				long userId = 0;
				if (userDTO != null) {
					userId = Long.parseLong(userDTO.getUserId());
					articleRating.setCreatedBy(userId);
				} else {
					articleRating.setCreatedBy(null);
				}
				articleRating.setCreatedIp(request.getRemoteAddr());
				
				if ("admin".equals(request.getAttribute(CommonConstants.USERNAME))) {
					// admin can do anything he/she wants ;)
					new ArticleRatingManager().save(articleRating);					
				} else {
					List<ArticleRating> articleRatings = new ArticleRatingManager().getRatingsByArticleId(articleId);
					if (isNewIpAddress(articleRatings, request)) { 
						if (userDTO == null) {
							// if you are not logged in or not a registered user, go ahead
							new ArticleRatingManager().save(articleRating);
						} else if (isNewUser(userId, articleRatings) && 
								!ActionSecurityUtils.isAuthor(userId, articleId)) {						
							// but if you are logged in from different Ip, we can check
							// if you are not about to cheat, trying to rate the same article again
							// this is clearly a discrimination of logged in users 
							// versus those who did not log in or those 
							// who do not have fi-post account at all ;)
							// do we need to restrict this to logged in users only?
							// also author can nor rate his/her own article
							new ArticleRatingManager().save(articleRating);
						} 
					} 
				}
				return new ActionForward("articlePresentationAction.do?articleId=" + articleId, true);

			} else {
				forward = ActionConstants.FAILURE;
			}
		} catch (NumberFormatException e) {
			log.error(e.getMessage());
			forward = ActionConstants.FAILURE;
		} catch (Exception e) {
			log.error(e.getMessage());
			forward = ActionConstants.SYSTEM_FAILURE;
		}

		return mapping.findForward(forward);
	}
	
	private boolean isNewIpAddress(List<ArticleRating> articleRatings, HttpServletRequest request) throws Exception {
		for (ArticleRating articleRating : articleRatings) {
			if (articleRating.getCreatedIp().equals(request.getRemoteAddr())) {
				return false;
			}
		}
		return true;
	}
	
	private boolean isNewUser(long userId, List<ArticleRating> articleRatings) throws Exception {
		for (ArticleRating articleRating : articleRatings) {
			if (articleRating.getCreatedBy() == userId) {
				return false;
			}
		}
		return true;
	}
	
}
